package com.ht.modules.system.online.cgreport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ht.modules.system.online.cgform.util.CgformUtil;
import com.ht.modules.system.online.cgreport.entity.OnlCgreportHead;
import com.ht.modules.system.online.cgreport.entity.OnlCgreportItem;
import com.ht.modules.system.online.cgreport.entity.OnlCgreportParam;
import com.ht.modules.system.online.cgreport.mapper.OnlCgreportHeadMapper;
import com.ht.modules.system.online.cgreport.model.OnlCgreportModel;
import com.ht.modules.system.online.cgreport.service.IOnlCgreportHeadService;
import com.ht.modules.system.online.cgreport.service.IOnlCgreportItemService;
import com.ht.modules.system.online.cgreport.service.IOnlCgreportParamService;
import com.ht.modules.system.online.cgreport.util.CgReportQueryParamUtil;
import com.ht.modules.system.online.cgreport.util.SqlUtil;
import com.ht.entity.Result;
import com.ht.exception.JeecgBootException;
import com.ht.utils.oConvertUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class OnlCgreportHeadServiceImpl extends ServiceImpl<OnlCgreportHeadMapper, OnlCgreportHead> implements IOnlCgreportHeadService {
  private static final Logger log = LoggerFactory.getLogger(OnlCgreportHeadServiceImpl.class);

  @Autowired
  private IOnlCgreportParamService onlCgreportParamService;

  @Autowired
  private IOnlCgreportItemService onlCgreportItemService;

  @Autowired
  OnlCgreportHeadMapper mapper;

  public Map<String, Object> executeSelectSql(String sql, Map<String, Object> params) {
    LambdaQueryWrapper<OnlCgreportParam> paramQuery = new LambdaQueryWrapper<>();
    paramQuery.eq(OnlCgreportParam::getCgrheadId, params.get("onlCgreportHeadId").toString());
    List<OnlCgreportParam> paramList = this.onlCgreportParamService.list(paramQuery);
    if (paramList != null && !paramList.isEmpty())
      for (OnlCgreportParam p : paramList) {
        Object value = params.get("self_" + p.getParamName());
        String valueStr = "";
        if (value != null) {
          valueStr = value.toString();
        } else if (oConvertUtils.isNotEmpty(p.getParamValue())) {
          valueStr = p.getParamValue();
        }
        sql = sql.replace("${" + p.getParamName() + "}", valueStr);
      }
    Map<String, Object> result = new HashMap<>();
    Integer pageSize = Integer.valueOf(oConvertUtils.getInt(params.get("pageSize"), 10));
    Integer pageNo = Integer.valueOf(oConvertUtils.getInt(params.get("pageNo"), 1));
    Page<Map<String, Object>> page = new Page<>(pageNo.intValue(), pageSize.intValue());
    LambdaQueryWrapper<OnlCgreportItem> query = new LambdaQueryWrapper<>();
    query.eq(OnlCgreportItem::getCgrheadId, params.get("onlCgreportHeadId").toString());
    query.eq(OnlCgreportItem::getIsSearch, Integer.valueOf(1));
    List<OnlCgreportItem> fieldList = this.onlCgreportItemService.list(query);
    String alias = "jeecg_rp_temp.";
    String condition = CgReportQueryParamUtil.getListQueryConditionSql(fieldList, params, alias);
    String querySql = "select * from (" + sql + ") jeecg_rp_temp  where 1=1 " + condition;
    Object orderColumn = params.get("column");
    if (orderColumn != null)
      querySql = querySql + " order by jeecg_rp_temp." + orderColumn.toString() + " " + params.get("order").toString();
    log.info("\r\n" + querySql);
    IPage<Map<String, Object>> pageList = this.mapper.selectPageBySql(page, querySql);
    result.put("total", Long.valueOf(pageList.getTotal()));
    result.put("records", CgformUtil.toLowerCasePageList(pageList.getRecords()));
    return result;
  }

  @Transactional(rollbackFor = {Exception.class})
  public Result<?> editAll(OnlCgreportModel values) {
    OnlCgreportHead head = values.getHead();
    OnlCgreportHead onlCgreportHeadEntity = (OnlCgreportHead)getById(head.getId());
    if (onlCgreportHeadEntity == null)
    	 return Result.error("未找到对应实体");
    updateById(head);
    List<OnlCgreportParam> params = values.getParams();
    List<OnlCgreportItem> items = values.getItems();
    List<OnlCgreportParam> addParam = new ArrayList<>();
    List<OnlCgreportParam> editParam = new ArrayList<>();
    for (OnlCgreportParam param : params) {
      String id = String.valueOf(param.getId());
      if (id.length() == 32) {
        editParam.add(param);
        continue;
      }
      param.setId(null);
      param.setCgrheadId(head.getId());
      addParam.add(param);
    }
    this.onlCgreportParamService.saveBatch(addParam);
    for (OnlCgreportParam edit : editParam)
      this.onlCgreportParamService.updateById(edit);
    List<OnlCgreportItem> addItem = new ArrayList<>();
    List<OnlCgreportItem> editItem = new ArrayList<>();
    for (OnlCgreportItem item : items) {
      String id = String.valueOf(item.getId());
      if (id.length() == 32) {
        editItem.add(item);
        continue;
      }
      item.setId(null);
      item.setCgrheadId(head.getId());
      addItem.add(item);
    }
    this.onlCgreportItemService.saveBatch(addItem);
    for (OnlCgreportItem edit : editItem)
      this.onlCgreportItemService.updateById(edit);
    this.onlCgreportParamService.removeByIds(values.getDeleteParamIdList());
    this.onlCgreportItemService.removeByIds(values.getDeleteItemIdList());
    return Result.ok("全部修改成功");
  }

  public List<String> getSqlFields(String sql, String dbKey) {
    List<String> fields = null;
    sql = SqlUtil.getSql(sql);
    if (StringUtils.isNotBlank(dbKey)) {
      fields = parseSql(sql, dbKey);
    } else {
      fields = parseSql(sql, null);
    }
    return fields;
  }

  public List<String> getSqlParams(String sql) {
    if (oConvertUtils.isEmpty(sql))
      return null;
    List<String> params = new ArrayList<>();
    String regex = "\\$\\{\\w+\\}";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(sql);
    while (m.find()) {
      String whereParam = m.group();
      params.add(whereParam.substring(whereParam.indexOf("{") + 1, whereParam.indexOf("}")));
    }
    return params;
  }


  private List<String> parseSql(String sql, String dbKey) {
    if (oConvertUtils.isEmpty(sql))
      return null;
    int pageNo = 1;
    int pageSize = 1;
    Page<Map<String, Object>> page = new Page(pageNo, pageSize);
    IPage<Map<String, Object>> pageList = this.mapper.selectPageBySql(page, sql);
    List<Map<String, Object>> result = pageList.getRecords();
    if (result.isEmpty())
    	 throw new JeecgBootException("该报表sql没有数据");
    Set<String> fieldsSet = ((Map)result.get(0)).keySet();
    List<String> fileds = new ArrayList<>();
    for (String f : fieldsSet)
      fileds.add(f.toLowerCase());
    return fileds;
  }

  public Map<String, Object> queryCgReportConfig(String reportId) {
    Map<String, Object> cgReportM = new HashMap<>(0);
    Map<String, Object> mainM = this.mapper.queryCgReportMainConfig(reportId);
    List<Map<String, Object>> itemsM = this.mapper.queryCgReportItems(reportId);
    List<String> params = this.mapper.queryCgReportParams(reportId);
    cgReportM.put("main", mainM);
    cgReportM.put("items", itemsM);
    cgReportM.put("params", params);
    return cgReportM;
  }

  public List<Map<?, ?>> queryByCgReportSql(String sql, Map params, Map paramData, int pageNo, int pageSize) {
    String querySql = SqlUtil.getFullSql(sql, params);
    List<Map<?, ?>> result = null;
    if (paramData != null && paramData.size() == 0)
      paramData = null;
    if (pageNo == -1 && pageSize == -1) {
      result = this.mapper.executeSelete(querySql);
    } else {
      Page<Map<String, Object>> page = new Page(pageNo, pageSize);
      IPage<Map<String, Object>> pageList = this.mapper.selectPageBySql(page, querySql);
      if (pageList.getRecords() != null && pageList.getRecords().size() > 0)
        result.addAll(pageList.getRecords());
    }
    return result;
  }
}
